package carsharing;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import aima.search.framework.Successor;
import aima.search.framework.SuccessorFunction;

public class CarsharingSuccessors implements SuccessorFunction {

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public List getSuccessorsHC(Object state)
	{
		ArrayList successors = new ArrayList();
	    Carsharing st = (Carsharing) state;
	    
	    System.out.println("Distancia Total: "+st.getDist());
	    System.out.println("Nombre de conductors: " + st.getNumAvailableDrivers());
	    

	    
	    int driv = st.getNumDrivers();
	    int memb = st.getNumMembers();
	    

	    //REASSIGN MEMBERS
	    int o;
	    Carsharing aux;
	    for(int i = 0; i < memb; ++i) {
    		if(!st.isDriver(i)) { //If is not a driver... reassign him to all the available drivers
		    	for(int j = 0; j < driv; ++j) {
		    		if(st.isDriverAvailable(j)) { //If the driver is available
		        		aux = new Carsharing(st);
			    		o = aux.reAssignMember(i, j); //Reassign the member to that driver with the best path
			    		if(o != -1) { //Then, if the member was extracted from another driver
			    			successors.add(new Successor("Reassignacio del membre " + i + " des del conductor " + o + " al conductor " + j , aux));
			    		}
			    		else { //If the member wasn't extracted from another driver, just add to successors
			    			successors.add(new Successor("Assignacio del membre " + i + " al conductor " + j, aux));
			    		}
		    		}
	    		}
	    	}
	    	
	    }
	    
	    //DRIVER REDUCTION
	    int membIdDriver;
    	for(int i = 0; i < driv; ++i) {
    		if(st.isDriverAvailable(i)) {
	    		membIdDriver = st.canReductDriver(i);
	    		if(membIdDriver != -1) { //Can be reduced
	    			for(int j = 0; j < driv; ++j) {
	    				if(st.isDriverAvailable(j) && i != j) { //Looking for an available driver different of herself
	    	        		aux = new Carsharing(st);
	    	        		aux.driverReduction(i, j);
		    	    		successors.add(new Successor("Reducci� del conductor " + i + " assignat al conductor " + j, aux));
	    				}
	    			}
	    		}
    		}
    	}
    	
		return successors;
	}
	
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public List getSuccessorsSA(Object state) {
		Random r = new Random();
		ArrayList successors = new ArrayList();
	    Carsharing st = (Carsharing) state;
	    
	    System.out.println("Distancia Total: "+st.getDist());
	    System.out.println("Nombre de conductors: " + st.getNumAvailableDrivers());
	    
		int operator = r.nextInt(2);
		int nMembers = st.getNumMembers();
		int nDrivers = st.getNumDrivers();
		
		int driverID, memberID, oldDriver;
		Carsharing aux = new Carsharing(st);
		
		switch(operator) {
			case 0: //DRIVER REDUCTION
				int reducibleDrivers = st.getNumReducibleDrivers();
				if(reducibleDrivers > 0) {
					driverID = r.nextInt(reducibleDrivers);
					int x = 0;
					for(int i = 0; i < nDrivers; ++i) {
						if(st.canReductDriver(i) != -1) {
							if(x == driverID) {
								driverID = i;
								break;//esto solo afecta al for verdad????
							}
							else ++x;
						}
					}
					
					oldDriver = driverID;
					driverID = r.nextInt(nDrivers);
					//Looking for another available driver
					while (!st.isDriverAvailable(driverID)) driverID = r.nextInt(nDrivers);
					aux.driverReduction(oldDriver, driverID);
					successors.add(new Successor("Reducci� del conductor " + oldDriver + " assignat al conductor " + driverID, aux));
					break;
				}
			case 1: //REASSIGN
					//Look for an available driver
					driverID = r.nextInt(nDrivers);
					while (!st.isDriverAvailable(driverID)) driverID = r.nextInt(nDrivers);
					memberID = r.nextInt(nMembers);
					while (st.isDriver(memberID)) memberID = r.nextInt(nMembers);
					oldDriver = aux.reAssignMember(memberID, driverID);
					if(oldDriver != -1) { //If the member was extracted from another driver
		    			successors.add(new Successor("Reassignacio del membre " + memberID + " des del conductor " + oldDriver + " al conductor " + driverID , aux));
		    		}
		    		else { //If the member wasn't extracted from another driver, just add to successors
		    			successors.add(new Successor("Assignacio del membre " + memberID + " al conductor " + driverID, aux));
		    		}
		    		break;
	    		
		}
		return successors;
	}

	@SuppressWarnings("rawtypes")
	public List getSuccessors(Object state) {
		return getSuccessorsHC(state);
		//return getSuccessorsSA(state);
	}

}
